/**
 * 
 */
package org.jenkon;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipFile;

import org.jenkon.iterator.ZipFileIterator;

/**
 * Search Classes in a spezific {@link ZipFile}.
 * 
 * @author Jens Konopka
 * 
 */
public class JarClassScanner extends AbstractClassScanner {

	/**
	 * 
	 */
	private static final long serialVersionUID = 4218737944581740351L;

	private final List<ZipFile> zipFiles = new ArrayList<ZipFile>();

	/**
	 * @param zipFile the {@link ZipFile} to search
	 */
	public JarClassScanner(final ZipFile... zipFiles) {
		this(Arrays.asList(zipFiles));
	}

	/**
	 * @param zipFiles the {@link List} with {@link ZipFile} objects.
	 */
	public JarClassScanner(final List<ZipFile> zipFiles) {
		this.zipFiles.addAll(zipFiles);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jenkon.commons.lang.ClassSearcher#search(java.lang.String)
	 */
	public List<Class<?>> scan(final String packageName) {
		final List<Class<?>> classes = new ArrayList<Class<?>>();
		for (final ZipFile zipFile : zipFiles) {
			classes.addAll(search(packageName, zipFile));
		}
		return classes;
	}

	/**
	 * @param packageName the name of the package
	 * @param zipFile the {@link ZipFile}
	 * @return {@link List} with {@link Class} objects
	 */
	private List<Class<?>> search(final String packageName, final ZipFile zipFile) {
		final List<Class<?>> classes = new ArrayList<Class<?>>();
		final ZipFileIterator iterator = new ZipFileIterator(zipFile);
		while (iterator.hasNext()) {
			final String entryName = iterator.next().getName();
			if (!entryName.startsWith(packageName.replace(".", "/")) || !entryName.toLowerCase().endsWith(".class")) {
				continue;
			}
			try {
				classes.add(getClass(entryName));
			} catch (Throwable ex) {
			}
		}
		return classes;
	}

	/**
	 * @param name the to create the {@link Class}
	 * @return the created {@link Class}
	 * @throws ClassNotFoundException class was not found
	 */
	private Class<?> getClass(final String name) throws ClassNotFoundException {
		return Class.forName(name.substring(0, name.length() - ".class".length()).replace("/", "."));
	}

}
